#!/bin/bash
# 死锁检测与修复脚本（无邮件通知版）
# 适用于Linux系统中检测到死锁（资源竞争）的情况
# 知识图谱关联配置 - 与故障节点ID对应
FIX_CODE_ID="deadlock-001"  # 对应知识图谱中"死锁（资源竞争）"故障ID


# 配置参数
LOG_FILE="/var/log/deadlock_fix.log"
WHITELIST_PROCESSES=("init" "systemd" "kernel" "sshd" "bash" "docker" "kubelet")  # 系统关键进程白名单
CHECK_INTERVAL=10            # 检查间隔时间(秒)
MAX_CHECK_TIMES=3            # 最大检查次数，超过该次数认为存在死锁

# 初始化日志
log() {
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    echo "[$timestamp] $1" >> $LOG_FILE
    echo "[$timestamp] $1"  # 同时输出到控制台
}

# 获取当前系统中可能存在资源竞争的进程
get_contending_processes() {
    # 通过lsof查找持有多个共享资源的进程
    local processes=$(lsof -w +M -n | awk '{print $2}' | sort | uniq -c | sort -nr | awk '$1 > 1 {print $2}')
    local contending_processes=""
    
    while read -r pid; do
        local is_whitelisted=0
        # 检查是否为白名单进程
        for process in "${WHITELIST_PROCESSES[@]}"; do
            if ps -p $pid -o comm= | grep -q "$process"; then
                is_whitelisted=1
                break
            fi
        done
        if [ $is_whitelisted -eq 0 ] && [ $pid -ne $$ ]; then  # 排除脚本自身
            contending_processes="$contending_processes $pid"
        fi
    done <<< "$processes"
    
    echo $contending_processes
}

# 检查是否存在死锁
check_deadlock() {
    local check_times=0
    local previous_processes=""
    
    while true; do
        local current_processes=$(get_contending_processes)
        
        if [ -z "$current_processes" ]; then
            log "未检测到可能存在资源竞争的进程"
            return 0  # 未发现死锁
        fi
        
        # 对比当前和之前的进程列表，判断是否持续存在资源竞争
        if [ "$previous_processes" = "$current_processes" ]; then
            ((check_times++))
            if [ $check_times -ge $MAX_CHECK_TIMES ]; then
                log "检测到可能存在死锁，相关进程: $current_processes"
                return 1  # 发现死锁
            fi
        else
            previous_processes="$current_processes"
            check_times=0
        fi
        
        sleep $CHECK_INTERVAL
    done
}

# 处理死锁相关进程
handle_deadlock_processes() {
    local processes=$(get_contending_processes)
    log "开始处理可能导致死锁的进程：$processes"
    
    for pid in $processes; do
        local cmd=$(ps -p $pid -o cmd --no-headers)
        log "尝试处理进程: PID=$pid, COMMAND=$cmd"
        
        # 先尝试优雅终止
        log "尝试优雅终止进程 $pid"
        kill -TERM $pid 2>/dev/null
        sleep 5
        
        # 检查进程是否已终止
        if ps -p $pid > /dev/null; then
            # 优雅终止失败，尝试强制终止
            log "进程 $pid 未能优雅终止，尝试强制终止"
            kill -KILL $pid 2>/dev/null
            sleep 2
            
            if ps -p $pid > /dev/null; then
                log "警告：进程 $pid 无法终止，需要人工干预"
            else
                log "进程 $pid 已强制终止"
            fi
        else
            log "进程 $pid 已优雅终止"
        fi
    done
    
    log "死锁处理完成"
}

# 主函数
main() {
    log "死锁检测与修复脚本启动"
    log "配置：检查间隔=$CHECK_INTERVAL秒，连续检查次数=$MAX_CHECK_TIMES"
    
    if check_deadlock; then
        # 0表示未检测到死锁
        log "系统未检测到死锁情况"
    else
        # 1表示检测到死锁，进行处理
        handle_deadlock_processes
    fi
}

# 启动主函数
main
